package com.zc.aspect;

import com.zc.annotation.SystemLogAnnotation;
import com.zc.mapper.SysLogMapper;
import com.zc.pojo.SysLog;
import com.zc.utils.JSONResult;
import com.zc.utils.JsonUtils;
import com.zc.utils.ZcUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.UUID;


/**
 * AOP的通知类型：
 * 1：前置通知 @Before
 * 2：后置通知 @After  注：After执行在AfterReturning之后
 * 3：环绕通知 @Around
 * 4：异常通知
 * 5：最终通知
 */

@Aspect
@Slf4j
@Component
public class SystemLogAspect {

    @Autowired
    SysLogMapper sysLogMapper;

    //统计请求的处理时间
    Long startTime = null;

    @Value("${spring.application.name}")
    private String appName;

    /**
     * 使用AOP处理请求:前置通知
     *
     * @throws Throwable
     */
    @Before("execution(* com.zc.controller..*.*(..))")
    public void printLogHttpBefore(JoinPoint joinPoint) {
        log.error("当前执行：{}", "HttpAspect.printLogHttpBefore");

        startTime = System.currentTimeMillis();

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();

        //url
        log.warn("url：{}", request.getRequestURI());

        //method
        log.warn("method：{}", request.getMethod());

        //ip
        log.warn("ip：{}", request.getRemoteAddr());

        //类方法
        log.warn("class_Method：{}.{}", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName());

        //请求参数
        log.warn("args：{}", joinPoint.getArgs());
    }

    /**
     * 使用AOP处理请求:后置通知返回结果
     */
    @AfterReturning(value = "execution(* com.zc.controller..*.*(..))", returning = "jsonResult")
    public void printLogHttpAfterReturning(JoinPoint joinPoint, JSONResult jsonResult) {
        log.error("当前执行：{}", "HttpAspect.printLogHttpAfterReturning");

        //保存日志
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        HttpServletResponse response = requestAttributes.getResponse();

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        //获取切入点所在的方法
        Method method = signature.getMethod();

        //获取操作
        String logContent = null;
        SystemLogAnnotation myOperation = method.getAnnotation(SystemLogAnnotation.class);
        if (myOperation != null) {
            logContent = myOperation.value();
        }

        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();

        SysLog systemLog = new SysLog();
        systemLog.setLogId(UUID.randomUUID().toString().replace("-", ""));
        systemLog.setLogName("API接口日志记录");
        systemLog.setLogContent(logContent);
        systemLog.setAppName(appName);
        systemLog.setRequestUrl(request.getRequestURL().toString());
        systemLog.setServerIp(ZcUtil.getServerIp());
        systemLog.setClientIp(request.getRemoteAddr());
        systemLog.setUserId(null);
        systemLog.setHttpMethod(request.getMethod());
        systemLog.setClientBrowser(null);
        systemLog.setClientOs(null);
        systemLog.setCreateTime(new Date());
        systemLog.setCreateUser(null);
        systemLog.setUpdateTime(new Date());
        systemLog.setUpdateUser(null);
        systemLog.setRequestParams(JsonUtils.obj2string(request.getParameterMap()));
        systemLog.setRequestResult(JsonUtils.obj2string(jsonResult));

        sysLogMapper.insert(systemLog);

        log.warn("response：{}", jsonResult.toString());
    }

    /**
     * 使用AOP处理请求:后置通知
     */
    @After("execution(* com.zc.controller..*.*(..))")
    public void printLogHttpAfter() {
        log.error("当前执行：{}", "HttpAspect.printLogHttpAfter");

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        //请求参数
        log.warn("url：{}", "");


    }


}
